﻿using System.Collections.Generic;
namespace GxFramework
{
    /// <summary>
    /// 模块逻辑控制系统，包含以下功能：
    /// 模块事件派发中心
    /// 模块数据请求/返回中转中心：只是中转事件，数据请求/解析/验证由Proxy处理
    /// 
    /// </summary>
    public interface ISystem
    {
        int systemID{get;}
        int executePriority { get; }

        void OnRegister();
        void OnStart();
        void OnStop();
        void Reset();
        void Update();
        void HandleEvent(int type,int value,string name,object body);
        void HandleInternalEvent(int type,int value,string name,object body);
    }
    /// <summary>
    /// 模块数据模型
    /// </summary>
    public interface IModel
    {
        int modelID { get; }
        void OnRegister();
        void OnStart();
        void OnStop();
        void Reset();
    }
    /// <summary>
    /// 应用：注册/管理 该应用的所有模块数据IModel和模块逻辑处理系统ISystem
    /// </summary>
    public class App
    {
        Dictionary<int, IModel> _modelMap = new Dictionary<int, IModel>();
        Dictionary<int, ISystem> _svcMap = new Dictionary<int, ISystem>();
        List<ISystem> _svcList = new List<ISystem>();
        public bool RegisterModel(IModel item)
        {
            IModel existItem;
            if (_modelMap.TryGetValue(item.modelID, out existItem))
                return false;
            _modelMap[item.modelID] = item;
            item.OnRegister();
            return true;
        }
        public IModel GetModel(int id)
        {
            IModel existItem;
            _modelMap.TryGetValue(id, out existItem);
            return existItem;
        }
        public bool RegisterSystem(ISystem item)
        {
            ISystem existItem;
            if (_svcMap.TryGetValue(item.systemID, out existItem))
                return false;
            _svcMap[item.systemID] = item;
            _svcList.Add(item);
            item.OnRegister();
            return true;
        }
        public ISystem GetSystem(int id)
        {
            ISystem existItem;
            _svcMap.TryGetValue(id, out existItem);
            return existItem;
        }
        public void Startup()
        {
            var iter = _modelMap.GetEnumerator();
            while(iter.MoveNext())
                iter.Current.Value.OnStart();

            var len = _svcList.Count;
            for (int i = 0; i < len; ++i)
                _svcList[i].OnStart();
        }
        public void ShutDown()
        {
            for (int i = _svcList.Count-1; i >= 0; --i)
                _svcList[i].OnStop();

            var iter = _modelMap.GetEnumerator();
            while(iter.MoveNext())
                iter.Current.Value.OnStop();
        }
        public void Reset()
        {
            for (int i = _svcList.Count-1; i >= 0; --i)
                _svcList[i].Reset();

            var iter = _modelMap.GetEnumerator();
            while(iter.MoveNext())
                iter.Current.Value.Reset();
        }
        public void Update()
        {
            var len = _svcList.Count;
            for (int i = 0; i < len; ++i)
                _svcList[i].Update();
        }
        public void InvokeSystem(int systemID, int type, int value=0, string name=null, object body=null)
        {
            ISystem item;
            if (!_svcMap.TryGetValue(systemID, out item))
                return;
            item.HandleInternalEvent(type,value,name,body);
        }
        public void InvokeAllSystems(int type, int value = 0, string name = null, object body = null, bool reverse=false)
        {
            var len = _svcList.Count;
            int index; 
            int step;
            if(reverse)
            {
                index = len-1;
                step = -1;
            }else
            {
                index = 0;
                step = 1;
            }
            for (int i = 0; i < len; index += step)
            {
                _svcList[index].HandleEvent(type, value, name, body);
            }
        }
    }
}